package com.ssttevee.taskmanagerapp;

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import com.ssttevee.taskmanagerapp.R;
import com.ssttevee.taskmanagerapp.tasks.ServerQuery;
import com.ssttevee.taskmanagerapp.tasks.Task;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class AddServerActivity extends Activity {

	private boolean changesPending;
	private boolean nameEmpty;
	private boolean online;
	private boolean qonline;
	private boolean edit = true;
	private int max_players;
	private int online_players;
	private int latency;
	private int gs4_port;
	private int times_online;
	private int times_checked;
	private int returnMsg;
	private long id;
	private String name;
	private String host;
	private String motd;
	private String players;
	private String version;
	private Button addButton;
	private Button cancelButton;
	private AlertDialog unsavedChangedDialog;
	private AlertDialog testDialog;
	private Task s;
	private ServerQuery sq = new ServerQuery();
	private ProgressBar loadSpinner;
	private TextView importantNote;
	private EditText fieldSName;
	private EditText fieldSAddr;
	private EditText fieldSPort;
	private EditText fieldQPort;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.add_task);
		viewSetup();
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			cancel();
			return false;
		}
		return super.onKeyDown(keyCode, event);
	}

	private void viewSetup() {
		Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/volter.ttf");
		fieldSName = (EditText)findViewById(R.id.sname_field);
		fieldSAddr = (EditText)findViewById(R.id.saddr_field);
		fieldSPort = (EditText)findViewById(R.id.sport_field);
		fieldQPort = (EditText)findViewById(R.id.qport_field);
		fieldSName.addTextChangedListener(new TextWatch(0, fieldSName.getText()));
		fieldSAddr.addTextChangedListener(new TextWatch(1, fieldSAddr.getText()));
		fieldSPort.addTextChangedListener(new TextWatch(2, fieldSPort.getText()));
		fieldQPort.addTextChangedListener(new TextWatch(3, fieldQPort.getText()));
		addButton = (Button)findViewById(R.id.add_task_btn);
		cancelButton = (Button)findViewById(R.id.cancel_add_task_btn);
		loadSpinner = (ProgressBar)findViewById(R.id.at_spinner);
		importantNote = (TextView)findViewById(R.id.important_note);
		fieldSAddr.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
		loadSpinner.setVisibility(View.INVISIBLE);
		addButton.setTypeface(tf);
		cancelButton.setTypeface(tf);
		cancelButton.setEnabled(false);
		
		Bundle extras = getIntent().getExtras(); 
		if(extras != null) {
			id = extras.getLong("id");
			name = extras.getString("name");
			host = extras.getString("host");
			motd = extras.getString("motd");
			max_players = extras.getInt("max_players");
			online_players = extras.getInt("online_players");
			players = extras.getString("players");
			latency = extras.getInt("latency");
			gs4_port = extras.getInt("gs4_port");
			version = extras.getString("version");
			times_online = extras.getInt("times_online");
			times_checked = extras.getInt("times_checked");
			online = extras.getBoolean("online");
		}
		importantNote.setText("NOTE: Query Port is not the Server Port.  If you don't know what it is, leave it blank.  It will cause connection failure.");
		addButton.setOnClickListener( new View.OnClickListener() {

			public void onClick(View v) {
				if(online == true) {
					addTask();
				}
			}
		});
		cancelButton.setOnClickListener( new View.OnClickListener() {
			public void onClick(View v) {
				check();
			}
		});
		
		if(id == 65535) {
			edit = false; 
		} else {
			fieldSName.setText(name);
			fieldSAddr.setText(host.split(":")[0]);
			fieldSPort.setText((host.contains(":") ? host.split(":")[1] : "25565"));
			fieldQPort.setText((gs4_port == 0 ? "" : gs4_port + ""));
			
			((TextView)findViewById(R.id.task_title)).setText("Edit " + name);
			addButton.setText("Save Changes");
			if(gs4_port > 0 && online) {
				returnMsg = 4;
			} else if(online) {
				returnMsg = 1;
			}
		}

		csUpdateUI();
	}

	protected void addTask() {
		int qport = 0;
		String sname = "Minecraft Server";
		TaskManagerApplication tma = (TaskManagerApplication) getApplication();

		if(fieldQPort.getText().length() > 0) {
			qport = Integer.parseInt(fieldQPort.getText().toString());
		}
		if(fieldSName.getText().length() > 0) {
			sname = fieldSName.getText().toString();
		}
		
		if(edit == true) {
			if(sq.isOnline() == false) {
				s = new Task(id, sname, fieldSAddr.getText().toString() + ":" + fieldSPort.getText().toString(), motd, max_players, online_players, players, latency, version, times_online, times_checked, online);
			} else {
				s = new Task(id, sname, fieldSAddr.getText().toString() + ":" + fieldSPort.getText().toString(), sq.getMotd(), sq.getMaxPlayers(), sq.getPlayerCount(), sq.getPlayers(), sq.getLatency(), sq.getVersion(), times_online + 1, times_checked + 1, online);
			}
			s.setGs4Port(qport);
			tma.saveTask(s);
			finish();
		} else {
			s = new Task(1024, sname, fieldSAddr.getText().toString() + ":" + fieldSPort.getText().toString(), sq.getMotd(), sq.getMaxPlayers(), sq.getPlayerCount(), sq.getPlayers(), sq.getLatency(), sq.getVersion(), sq.getTimesOnline(), sq.getTimesChecked(), online);
			s.setGs4Port(qport);
			tma.addTask(s);
			finish();
		}
		overridePendingTransition(R.anim.in_from_left, R.anim.out_to_right);
	}
	
	protected void csUpdateUI() {
		if(returnMsg == 0 || returnMsg == 2 || returnMsg == 3) {
			addButton.setEnabled(false);
		} else if (returnMsg == 1 || returnMsg == 4) {
			if(qonline == false && fieldQPort.getText().length() > 0) {
				addButton.setEnabled(false);
			} else if(qonline == true) {
				addButton.setEnabled(true);
			} else {
				addButton.setEnabled(true);
			}
			if(online == true) {
				addButton.setEnabled(true);
			} else if(online == false) {
				addButton.setEnabled(true);
			}
		}
	}

	protected void check() {
		if(isInternetAvailable()) {
			boolean saddr = false;
			boolean sport = false;
			boolean qport = false;
			SudoMethod sm = new SudoMethod();
			if(fieldSAddr.getText().length() <= 0) {
				Toast.makeText(getBaseContext(), "Server address is missing", Toast.LENGTH_SHORT).show();
			} else if(!sq.validateAddress(fieldSAddr.getText().toString().split(":")[0])) {
				Toast.makeText(getBaseContext(), "Unable to find host", Toast.LENGTH_SHORT).show();
			} else {
				saddr = true;
			}
			
			if(fieldSPort.getText().length() <= 0) {
				Toast.makeText(getBaseContext(), "Server Port is missing", Toast.LENGTH_SHORT).show();
			} else if(Integer.parseInt(fieldSPort.getText().toString()) > 65535) {
				Toast.makeText(getBaseContext(), "Query Port is too big", Toast.LENGTH_SHORT).show();
			} else if(!(Integer.parseInt(fieldSPort.getText().toString()) > 0)) {
				Toast.makeText(getBaseContext(), "Query Port is too small", Toast.LENGTH_SHORT).show();
			} else {
				sport = true;
			}

			if(fieldQPort.getText().length() <= 0) {
			} else if(Integer.parseInt(fieldQPort.getText().toString()) > 65535) {
				Toast.makeText(getBaseContext(), "Query Port is too big", Toast.LENGTH_SHORT).show();
			} else if(!(Integer.parseInt(fieldQPort.getText().toString()) > 0)) {
				Toast.makeText(getBaseContext(), "Query Port is too small", Toast.LENGTH_SHORT).show();
			} else {
				qport = true;
			}
			
			if(saddr == true) {
				if(qport == true) {
					sm.execute("both");
					cancelButton.setEnabled(false);
				} else if(sport == true) {
					sm.execute("poll");
					cancelButton.setEnabled(false);
				}
			}
			
		} else {
			Toast.makeText(getBaseContext(), "Network Unavailable", Toast.LENGTH_SHORT).show();
		}
		
	}

	protected void cancel() {
		if(changesPending) {
			unsavedChangedDialog = new AlertDialog.Builder(this)
				.setTitle(R.string.unsaved_changed_title)
				.setMessage("Do you really want to lose this data?")
				.setNeutralButton(R.string.discard, new AlertDialog.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						finish();
						overridePendingTransition(R.anim.in_from_right, R.anim.out_to_left);
					}
				})
				.setNegativeButton(R.string.cancel, new AlertDialog.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						unsavedChangedDialog.cancel();
					}
				}).create();
			unsavedChangedDialog.show();
		} else {
			finish();
			overridePendingTransition(R.anim.in_from_left, R.anim.out_to_right);
		}
	}

	protected void sendPopup(String title, String msg) {
		testDialog = new AlertDialog.Builder(this)
			.setTitle(title)
			.setMessage(msg)
			.setNeutralButton("Alright...", new AlertDialog.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					testDialog.cancel();
				}
			}).create();
		testDialog.show();
	}
	
	public boolean isInteger(String input) {
		try {
			Integer.parseInt(input);
			return true;
		} catch(Exception e) {
			return false;
		}
	}
	
	public boolean isInternetAvailable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		return activeNetworkInfo != null;
	}

	public void showSpinner() {
		loadSpinner.setVisibility(View.VISIBLE);
	}
	
	public void hideSpinner() {
		loadSpinner.setVisibility(View.INVISIBLE);
	}

	public boolean isNameEmpty() {
		return nameEmpty;
	}

	public void setNameEmpty(boolean nameEmpty) {
		this.nameEmpty = nameEmpty;
	}

	private class SudoMethod extends AsyncTask<String, Integer, String> {
		private String[] messages = new String[]{"Connection Refused", "Connection Successful", "Unable to find host", "Query Attempt Failed", "Query Request Successful"};

		public SudoMethod() {
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showSpinner();
		}
		
		@Override
		protected String doInBackground(String... params) {
			if(params[0] == "poll") {
				poll();
			} else if(params[0] == "query") {
				query();
			} else if(params[0] == "both") {
				query();
				poll();
			}
			return "All Done!";
		}
		
		private void poll() {
			try {
				sq.pollServer(new Task(0, null, fieldSAddr.getText().toString() + ":" + fieldSPort.getText().toString(), null, 0, 0, null, 0, null, 0, 0, changesPending));
				online = true;
				returnMsg = 1;
			} catch (IOException e) {
				online = false;
				returnMsg = 0;
			}
		}

		private void query() {
			try {
				Task g = new Task(0, null, fieldSAddr.getText() + ":" + fieldSPort.getText(), null, 0, 0, null, 0, null, 0, 0, changesPending);
				g.setGs4Port(Integer.parseInt(fieldQPort.getText().toString()));
				InetAddress ipAddr = sq.parseIp(fieldSAddr.getText().toString());
				DatagramSocket dp = sq.initConnection(ipAddr, g.getGs4Port());
				sq.queryServer(g, ipAddr, dp);
				returnMsg = 4;
				qonline = true;
				online = true;
			} catch(UnknownHostException e) {
				online = false;
				qonline = false;
				returnMsg = 2;
			} catch (IOException e) {
				online = false;
				qonline = false;
				returnMsg = 3;
			}
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
		}
		
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			Toast.makeText(getBaseContext(), messages[returnMsg], Toast.LENGTH_SHORT).show();
			hideSpinner();
			csUpdateUI();
		}
	}
	
	private class TextWatch implements TextWatcher {
        private int id;
        private Editable ed;

        public TextWatch(int id, Editable s) {
                this.id = id;
                this.ed = s;
        }

        public void afterTextChanged(Editable s) {
        	boolean addr = false;
        	boolean port = false;
        	boolean qport = false;
        	if(this.id == 0) {
        		return;
        	}
        	if(fieldSAddr.getText().length() > 0) {
        		addr = true;
        	}
        	if(fieldSPort.getText().length() > 0) {
        		port = true;
        	}
        	if(fieldQPort.getText().length() > 0) {
        		qport = true;
        	}
        	
        	
        	if(addr && port) {
        		cancelButton.setEnabled(true);
        	} else {
        		cancelButton.setEnabled(false);
        	}
        }

		public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
		}

		public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
		}
}
}
